צריך לכתוב שיטה רקורסיבית שתקבל מערך של מספרים, טווח של המערך, בשביל הרקורסיה, ומספר.
היא תחזיר אמת אם קיים צירוף מסויים של חיבור וחיסור בין המספרים במערך שיתן את המספר כתוצאה.
ניסיתי הרבה דברים, לא הצלחתי להגיע לתוצאה מושלמת.
אשמח לתשובה מהירה כי אני צריך את זה לשבוע הזה. תודה רבה!
דוגמה לנסיון:
public class P {
  public static boolean find(int[] A, int n, int num) {
    if (n <= 0)
      return false;
    if (n == 1)
      return A[0] == num || A[0] == num*(-1);
    return find(A, n-1, num+A[n]) || find(A, n-1, num-A[n]);
  }
  public static void main(String[] args) {
    int[] a = {3,2,5};
    System.out.println(find(a,a.length-1, 0));
  }

}

7 תשובות

avatar ענה intval ב 31 למרץ 2015 #

/* package whatever; // don't place package name! */

import java.util.*;
import java.lang.*;
import java.io.*;

/* Name of the class has to be "Main" only if the class is public. */
class Ideone
{
  public static void main (String[] args) throws java.lang.Exception
  {
    int[] a = { 3, 8, 5, 1, 6};

    assert1(find(a, 2) == true); // ignored +8 -5 -1 ignored = 2
    assert1(find(a, 11) == true); // +3 +8 ign ign ign = 11
    assert1(find(a, 200) == false); // !
    assert1(find(a, 3) == true); // +3 ign ign ign ign = 3
    assert1(find(a, 7) == true); // ign ign ign +1 +6 = 7
    assert1(find(a, 4) == true); // ign, ign, +5 -1 ign = 4
    assert1(find(new int[0], 0) == false); //!
    //assert1(false == true);
  }
 

  public static boolean find(int[] array, int expectedSum)
  {
    return find(array, expectedSum, 0, 0);
  }

  public static boolean find(int[] array, int expectedSum, int startIndex, long sumUpToStartIndex) {
    if(array.length < 1 || startIndex >= array.length)
      return false;
     
    int currentValue = array[startIndex];
    long tryToAddSum = sumUpToStartIndex + currentValue;
    long tryToSubSum = sumUpToStartIndex - currentValue;
   
    if(tryToAddSum == expectedSum || tryToSubSum == expectedSum)
      return true;
   
    // try to continue as if we had added
    // or try to continue as if we had subtracted
    // and then try as if we had just started from the next element and ignored everything before
    return  find(array, expectedSum, startIndex+1, tryToAddSum) ||
        find(array, expectedSum, startIndex+1, tryToSubSum) ||
        find(array, expectedSum, startIndex+1, 0);
  }


  private static void assert1(boolean expr) throws IllegalArgumentException
  {
    //if(!expr)
    //  throw new IllegalArgumentException("assertion has failed");
   
    System.out.println("assertion has " + (expr?"passed" : "failed"));
  }


}


http://ideone.com/rFnKk2

avatar ענה yossi787 ב 01 לאפריל 2015 #

תודה, אבל אתה בטוח שזה הפתרון הכי פשוט?

avatar ענה intval ב 01 לאפריל 2015 #

לא,
אבל אם מה שמפריע לך זה כמות השורות - חצי מהם אפשר לזרוק או לקצר..

avatar ענה yossi787 ב 01 לאפריל 2015 #

לא הכמות, אני בקורס ג'אווה וזו הייתה שאלה בחחינה אז לא הגיוני שזו תהיה התשובה (לבחינה) כי חלק מזה לא למדנו וזה אמור להיות תשובה קצרה.

avatar ענה Splash ב 01 לאפריל 2015 #

אין דבר כזה,כל הפעולות שיש כאן הן בסיסיות,חיבור,חיסור ורקורסיה הדבר היחיד שאתה כן יכול להגיד זה שברמה אלגוריתמית לא יצא לכם לחשוב ברמה הזאת וזה כבר אשמתו של המורה שבעצם דפק את כל התלמידים כי לימד אותם רק איך לכתוב קוד בלי לדעת איך לחשוב.

avatar ענה yossi787 ב 01 לאפריל 2015 #

לא ממש.. התכוונתי נגיד ל:

throws IllegalArgumentException

שאני לא יודע אם זה כזה חיוני לקוד אבל לא למדנו את זה.

avatar ענה Splash ב 01 לאפריל 2015 #

כל המתודה assert1 היא חסרת משמעות התפקיד שלה בסך הכל להגיד "אפשר" או "אי אפשר"
מאחר ונדרשת לכתוב רק את המתודה הרקורסיבית בפועל גם אין צורך ב main עצמו.